/**
 * 
 */
package com.primestone.cim.meterreadings.util;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.primestone.cim.meterreadings.beans.Key;
import com.primestone.cim.meterreadings.beans.MaxMinDate;
import com.primestone.cim.meterreadings.beans.MaxMinDateForDB;
import com.primestone.cim.meterreadings.beans.ReadingsQueryResult;
import com.primestone.cim.util.DateUtil;
import com.primestone.cim.util.StringUtil;
import com.primestone.cim.util.enums.SocDevEnum;

/**
 * @author cesar.mateus
 *
 */
public class MaxMinDateUtil {

	/**
	 * 
	 * @param maxMinDateList
	 * @return
	 */
	public static Map<String, MaxMinDateForDB> transformMaxMinDate(List<MaxMinDate> maxMinDateList) {
		Map<String, MaxMinDateForDB> mapForDB = new HashMap<String, MaxMinDateForDB>();
		Set<String> keySet = mapForDB.keySet();
		String key;
		MaxMinDateForDB eachRecord;
		for (MaxMinDate maxMinDate : maxMinDateList) {
			key = maxMinDate.getIdSocketOrDevice();
			
			if (keySet.contains(key)) {
				eachRecord = mapForDB.get(key);
			} else {
				eachRecord = new MaxMinDateForDB();
				eachRecord.setIdSocketOrDevice(key);
				eachRecord.setSocketOrDevice(maxMinDate.getSocketOrDevice());
			}
			
			if (maxMinDate.getVarType().equals(StringUtil.VARTYPE_LP)) {
				eachRecord.setMaxDateM(maxMinDate.getMaxDate());
				eachRecord.setMinDateM(maxMinDate.getMinDate());
			} else if (maxMinDate.getVarType().equals(StringUtil.VARTYPE_REG)) {
				eachRecord.setMaxDateR(maxMinDate.getMaxDate());
				eachRecord.setMinDateR(maxMinDate.getMinDate());
			} else if (maxMinDate.getVarType().equals(StringUtil.VARTYPE_EVE)) {
				eachRecord.setMaxDateV(maxMinDate.getMaxDate());
				eachRecord.setMinDateV(maxMinDate.getMinDate());
			}
			
			mapForDB.put(key, eachRecord);
		}
		
		return mapForDB;
	}
	
	/**
	 * Del conjunto de resultados pasado, devuelve una lista de noins/vartype/fechas max y min
	 * @param queryResult
	 * @param socketOrDevice 
	 * @return 
	 */
	public static List<MaxMinDate> getMinMaxDates(List<ReadingsQueryResult> queryResult, String socketOrDevice) {
		// Organizar queryResult en un map por noins, vartype y fechas.
		Map<Key, List<ReadingsQueryResult>> map = new HashMap<Key, List<ReadingsQueryResult>>();
		populateMap(map, queryResult, socketOrDevice);
		Set<Key> keySet = map.keySet();
		List<ReadingsQueryResult> classifiedResults;
		List<Date> maxMinDates;
		List<MaxMinDate> maxMinDatesByNoinsByVarType = new ArrayList<MaxMinDate>();
		for (Key key : keySet) {
			classifiedResults = map.get(key);
			maxMinDates = getMaxMinDatesList(classifiedResults);
			maxMinDatesByNoinsByVarType.add(
					new MaxMinDate(
						key.getIdDeviceOrSocket(),
						key.getVarType(),
						maxMinDates.get(0),
						maxMinDates.get(1),
						socketOrDevice
						));
		}
		return maxMinDatesByNoinsByVarType;
	}
	
	/**
	 * 
	 * @param results
	 * @param maxMinDates
	 */
	private static List<Date> getMaxMinDatesList(List<ReadingsQueryResult> results) {
		List<Date> maxMinDates = new ArrayList<Date>();
		Date maxDate = DateUtil.MIN_DATE;
		Date minDate = DateUtil.MAX_DATE;
		for (ReadingsQueryResult result : results) {
			if (result.getDatetime().before(minDate)) {
				minDate = result.getDatetime();
			}
			
			if (result.getDatetime().after(maxDate)) {
				maxDate = result.getDatetime();
			}
		}
		
		maxMinDates.add(maxDate);
		maxMinDates.add(minDate);
		return maxMinDates;
	}
	
	/**
	 * 
	 * @param map
	 * @param queryResult
	 * @param socketOrDevice 
	 */
	private static void populateMap(Map<Key, List<ReadingsQueryResult>> map, List<ReadingsQueryResult> queryResult, String socketOrDevice) {
		List<ReadingsQueryResult> readingsQueryResult;
		Set<Key> keySet = map.keySet();
		Key key;
		for (ReadingsQueryResult rqr : queryResult) {
			if (socketOrDevice.equals(SocDevEnum.WORK_SOCKETS.getCode())) {
				key = new Key(rqr.getIdSocket(), rqr.getVarType());	
			} else { // Sino, se trata de SocDevEnum.WORK_DEVICES
				key = new Key(rqr.getIdDevice(), rqr.getVarType());
			}
			
			if (keySet.contains(key)) {
				readingsQueryResult = map.get(key);
			} else {
				readingsQueryResult = new ArrayList<ReadingsQueryResult>();
			}
			readingsQueryResult.add(rqr);
			map.put(key, readingsQueryResult);
		}
	}

}
